<script setup lang="ts">
import {
  deleteCartAPI,
  getCartListAPI,
  updateAllSelectedAPI,
  updateCartAPI,
} from '@/services/cart'
import { useMemberStore } from '@/stores'
import type { CartItem } from '@/types/cart'
import { onPullDownRefresh, onReachBottom, onShow } from '@dcloudio/uni-app'
import { storeToRefs } from 'pinia'
import { computed, ref } from 'vue'
// @ts-ignore
import { debounce } from 'lodash'
import type { InputNumberBoxEvent } from '@/components/vk-data-input-number-box/vk-data-input-number-box'
import useCustomGuess from '@/hooks/useCustomGuess'

// 获取用户仓库中的用户信息
const { profile } = storeToRefs(useMemberStore())
// 购物车列表
const cartList = ref<CartItem[]>([])
// 获取猜你喜欢组件的组件实例对象和上拉加载更多的方法
const { guessRef, onScrolltolower } = useCustomGuess()
// 获取屏幕安全距离
const { safeAreaInsets } = uni.getSystemInfoSync()

defineProps<{
  // 是否对底部工具栏进行安全适配
  bottomSafeFit?: boolean
}>()

// 获取购物车商品数据
const getCartList = async () => {
  const res = await getCartListAPI()
  // 存储购物车商品数据
  cartList.value = res.result
}
// 删除按钮的回调
const onDeleteCart = async (skuId: string) => {
  // 调用接口删除商品
  await deleteCartAPI({ ids: [skuId] })
  // 提示删除成功
  uni.showToast({
    title: '删除成功',
    icon: 'none',
  })
  // 重新获取商品数据
  getCartList()
}
// 方案一:修改商品数量的回调(防抖优化)
const onChangeCount = debounce(async (event: InputNumberBoxEvent) => {
  // {index,value} = event  index:当前步进器的标识 value:当前步进器的值
  await updateCartAPI(event.index, { count: event.value })
}, 1000)
/* 方案二:修改商品数量的回调(防抖优化)
const onChangeCount = debounce(async (count: number, skuId: string) => {
  // 调用接口修改商品数量
  await updateCartAPI(skuId, { count })
}, 1000) */
// 计算是否全选
let isAllSelected = computed(() => {
  return cartList.value.length && cartList.value.every((item) => item.selected)
})
// 更改单个商品选中状态的回调
const onChangeGoodsSelected = async (item: CartItem) => {
  // 修改前端数据
  // console.log(item) // Proxy{} 响应式数据修改会影响到cartList
  item.selected = !item.selected
  // 修改当前商品的选中状态(修改后端数据)
  await updateCartAPI(item.skuId, { selected: !item.selected })
  // (通过重新获取商品数据来实现状态更新，效率较低，网络不好时有明显延迟，采用直接修改本地数据)
  // getCartList()
}
// 全选/全不选的回调
const onChangeAllSelected = async () => {
  // 修改前端数据
  // 由于isAllSelected会在cartList被修改后重新进行计算,会变化所以将其原始值进行缓存
  let newAllSelect = !isAllSelected.value
  // 前端数据更新
  cartList.value.forEach((item) => {
    item.selected = newAllSelect
  })
  // 发请求更改当前全选的状态(修改后端数据)
  await updateAllSelectedAPI({ selected: newAllSelect })
  // (通过重新获取商品数据来实现状态更新，效率较低，网络不好时有明显延迟，采用直接修改本地数据)
  // getCartList()
}
// 计算被选中的商品列表
const selectedGoodsList = computed(() => {
  // 过滤选中的商品，返回一个数组
  return cartList.value.filter((item) => item.selected)
})
// 计算选中商品的总金额
let selectedGoodsMoney = computed(() => {
  return selectedGoodsList.value
    .reduce((total, item) => total + item.nowPrice * item.count, 0)
    .toFixed(2)
})
// 计算选中商品的总数
let selectGoodsCount = computed(() => {
  return selectedGoodsList.value.reduce((total, item) => total + item.count, 0)
})
// 去结算按钮回调
const toPayment = () => {
  // 未选择任何商品的提示
  if (!selectGoodsCount.value)
    return uni.showToast({
      title: '请选择商品',
      icon: 'none',
    })
  // 跳转到结算页面
  uni.navigateTo({
    url: '/pagesOrder/create/create',
  })
}

// 页面展示
onShow(() => {
  // 判断用户是否登录
  if (!profile.value?.token) return
  // 获取商品数据
  getCartList()
})
// 上拉加载更多
onReachBottom(() => {
  onScrolltolower()
})
// 下拉刷新
onPullDownRefresh(async () => {
  // 重新获取购物车和猜你喜欢的数据
  await Promise.all([getCartList(), guessRef.value?.resetData()])
  // 关闭刷新框
  uni.stopPullDownRefresh()
})
</script>

<template>
  <view class="cart">
    <!-- 已登录: 显示购物车 -->
    <template v-if="profile?.token">
      <!-- 购物车列表 -->
      <view class="cart-list" v-if="cartList.length">
        <!-- 优惠提示 -->
        <view class="tips">
          <text class="label">满减</text>
          <text class="desc">满1件, 即可享受9折优惠</text>
        </view>
        <!-- 滑动操作分区 -->
        <uni-swipe-action>
          <!-- 滑动操作项 -->
          <uni-swipe-action-item
            v-for="item in cartList"
            :key="item.skuId"
            class="cart-swipe"
          >
            <!-- 商品信息 -->
            <view class="goods">
              <!-- 选中状态 -->
              <text
                class="checkbox"
                :class="{ checked: item.selected }"
                @tap="onChangeGoodsSelected(item)"
              ></text>
              <navigator
                :url="`/pages/goods/goods?id=${item.id}`"
                hover-class="none"
                class="navigator"
              >
                <image mode="aspectFill" class="picture" :src="item.picture"></image>
                <view class="meta">
                  <view class="name ellipsis">{{ item.name }}</view>
                  <view class="attrsText ellipsis">{{
                    item.attrsText.replace('，', ' ')
                  }}</view>
                  <!-- 商品价格 -->
                  <view class="price">{{
                    (item.nowPrice * item.count).toFixed(2)
                  }}</view>
                </view>
              </navigator>
              <!-- 商品数量 -->
              <view class="count">
                <!-- 方案一:使用SKU组件提供的步进器组件vk-data-input-number-box -->
                <vk-data-input-number-box
                  v-model="item.count"
                  :min="0"
                  :max="item.stock"
                  :index="item.skuId"
                  @change="onChangeCount"
                />
                <!-- 方案二:使用uni-ui提供的数字输入框组件 -->
                <!-- <uni-number-box
                  :min="0"
                  :max="item.stock"
                  :step="1"
                  v-model="item.count"
                  @change="onChangeCount(item.count, item.skuId)"
                /> -->
              </view>
            </view>
            <!-- 右侧删除按钮插槽 -->
            <template #right>
              <view class="cart-swipe-right">
                <button class="button delete-button" @tap="onDeleteCart(item.skuId)">
                  删除
                </button>
              </view>
            </template>
          </uni-swipe-action-item>
        </uni-swipe-action>
      </view>
      <!-- 购物车空状态 -->
      <view class="cart-blank" v-else>
        <image src="/static/images/blank_cart.png" class="image" />
        <text class="text">购物车还是空的，快来挑选好货吧</text>
        <navigator open-type="switchTab" url="/pages/index/index" hover-class="none">
          <button class="button">去首页看看</button>
        </navigator>
      </view>
      <!-- 吸底工具栏 -->
      <view
        class="toolbar"
        :style="bottomSafeFit && `padding-bottom:${safeAreaInsets?.bottom}px`"
      >
        <text
          class="all"
          :class="{ checked: isAllSelected }"
          @tap="onChangeAllSelected"
          >全选</text
        >
        <text class="text">合计:</text>
        <text class="amount">{{ selectedGoodsMoney }}</text>
        <view class="button-grounp">
          <view
            class="button payment-button"
            :class="{ disabled: !selectGoodsCount }"
            @click="toPayment"
          >
            去结算({{ selectGoodsCount }})
          </view>
        </view>
      </view>
    </template>
    <!-- 未登录: 提示登录 -->
    <view class="login-blank" v-else>
      <text class="text">登录后可查看购物车中的商品</text>
      <navigator url="/pages/login/login" hover-class="none">
        <button class="button">去登录</button>
      </navigator>
    </view>
    <!-- 猜你喜欢 -->
    <CustomGuess ref="guessRef"></CustomGuess>
    <!-- 底部占位空盒子 -->
    <view
      class="toolbar-height"
      :style="bottomSafeFit && `margin-top:${safeAreaInsets?.bottom}px`"
    ></view>
  </view>
</template>

<style lang="scss">
// 根元素
.cart {
  background-color: #f7f7f8;
  padding-top: 20rpx;
}
// }
// 购物车列表
.cart-list {
  padding: 0 20rpx;
  // 优惠提示
  .tips {
    display: flex;
    align-items: center;
    line-height: 1;
    margin: 10rpx 10rpx 30rpx 10rpx;
    font-size: 26rpx;
    color: #666;
    .label {
      color: #fff;
      padding: 7rpx 15rpx 5rpx;
      border-radius: 4rpx;
      font-size: 24rpx;
      background-color: #27ba9b;
      margin-right: 10rpx;
    }
  }
  // 购物车商品
  .goods {
    display: flex;
    padding: 20rpx 20rpx 20rpx 80rpx;
    border-radius: 10rpx;
    background-color: #fff;
    position: relative;
    .navigator {
      display: flex;
    }
    .checkbox {
      position: absolute;
      top: 0;
      left: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 80rpx;
      height: 100%;
      &::before {
        content: '\e6cd';
        font-family: 'erabbit' !important;
        font-size: 40rpx;
        color: #444;
      }
      &.checked::before {
        content: '\e6cc';
        color: #27ba9b;
      }
    }
    .picture {
      width: 170rpx;
      height: 170rpx;
    }
    .meta {
      flex: 1;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      margin-left: 20rpx;
    }
    .name {
      height: 72rpx;
      font-size: 26rpx;
      color: #444;
    }
    .attrsText {
      line-height: 1.8;
      padding: 0 15rpx;
      font-size: 24rpx;
      align-self: flex-start;
      border-radius: 4rpx;
      color: #888;
      background-color: #f7f7f8;
    }
    .price {
      line-height: 1;
      font-size: 26rpx;
      color: #444;
      margin-bottom: 2rpx;
      color: #cf4444;
      &::before {
        content: '￥';
        font-size: 80%;
      }
    }
    // 商品数量
    .count {
      position: absolute;
      bottom: 10rpx;
      right: 5rpx;
      :deep(.uni-numbox) {
        font-size: 26rpx;
        width: 200rpx;
        height: 40rpx;
        overflow: hidden;
        .uni-numbox-btns {
          width: 60rpx;
          height: 40rpx;
        }
        .uni-numbox__value {
          font-size: 26rpx;
          height: 40rpx !important;
          padding-bottom: 30rpx;
          box-sizing: border-box;
        }
      }
    }
  }
  .cart-swipe {
    display: block;
    margin: 20rpx 0;
  }
  .cart-swipe-right {
    display: flex;
    height: 100%;
    .button {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 50px;
      padding: 6px;
      line-height: 1.5;
      color: #fff;
      font-size: 26rpx;
      border-radius: 0;
    }
    .delete-button {
      background-color: #cf4444;
    }
  }
}
// 空状态
.cart-blank,
.login-blank {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  height: 60vh;
  .image {
    width: 400rpx;
    height: 281rpx;
  }
  .text {
    color: #444;
    font-size: 26rpx;
    margin: 20rpx 0;
  }
  .button {
    width: 240rpx !important;
    height: 60rpx;
    line-height: 60rpx;
    margin-top: 20rpx;
    font-size: 26rpx;
    border-radius: 60rpx;
    color: #fff;
    background-color: #27ba9b;
  }
}
// 吸底工具栏
.toolbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: var(--window-bottom);
  z-index: 1;
  height: 100rpx;
  padding: 0 20rpx;
  display: flex;
  align-items: center;
  border-top: 1rpx solid #ededed;
  border-bottom: 1rpx solid #ededed;
  background-color: #fff;
  box-sizing: content-box;
  .all {
    margin-left: 25rpx;
    font-size: 14px;
    color: #444;
    display: flex;
    align-items: center;
  }
  .all::before {
    font-family: 'erabbit' !important;
    content: '\e6cd';
    font-size: 40rpx;
    margin-right: 8rpx;
  }
  .checked::before {
    content: '\e6cc';
    color: #27ba9b;
  }
  .text {
    margin-right: 8rpx;
    margin-left: 32rpx;
    color: #444;
    font-size: 14px;
  }
  .amount {
    font-size: 20px;
    color: #cf4444;
    .decimal {
      font-size: 12px;
    }
    &::before {
      content: '￥';
      font-size: 12px;
    }
  }
  .button-grounp {
    margin-left: auto;
    display: flex;
    justify-content: space-between;
    text-align: center;
    line-height: 72rpx;
    font-size: 13px;
    color: #fff;
    .button {
      width: 240rpx;
      margin: 0 10rpx;
      border-radius: 72rpx;
    }
    .payment-button {
      background-color: #27ba9b;
      &.disabled {
        opacity: 0.6;
      }
    }
  }
}
// 底部占位空盒子
.toolbar-height {
  height: 100rpx;
}
</style>
